"use strict";

var renderer_printDebug = false;

function Renderer() {
	this.positionOffset = $V([100.0, -100.0]);
	this.positionScale = $V([20.0, 20.0]);
	this.lengthScale = 20.0;
	
	this.objects = Array();
	
	this.getCanvas = function() {
		var canvas = document.getElementById("canvas");
		return canvas;
	}
	this.getContext = function() {
		var canvas = this.getCanvas();
		var context = canvas.getContext("2d");
		return context;
	}
	
	// used in favour of this.loadPhysicsRenderMatrix()
	this.physicsCoords2Pixels = function(position) {
		var o = this.positionOffset.elements;
		var s = this.positionScale.elements;
		var p = position.elements;
		var h = this.getCanvas().height;
		
		return $V([
			+p[0]*s[0] + o[0],
			-p[1]*s[1] + o[1] + h]);
	}
	this.physicsLength2Pixels = function(length) {
		return length*this.lengthScale;
	}
	this.pixels2PhysicsCoords = function(position) {
		var o = this.positionOffset.elements;
		var s = this.positionScale.elements;
		var r = position.elements;
		var h = this.getCanvas().height;
		
		return $V([
			(r[0] - o[0])/s[0],
			(h - r[1] + o[1])/s[1]]);
	}
	// unused because this.physicsCoords2Pixels() is used instead
	this.loadPhysicsRenderMatrix = function() {
		v = this.positionScale.elements;
		p = this.positionOffset.elements;
		
		this.getContext().setTransform(v[0], 0, 0, v[1], p[0], p[1]);
	}
	this.getObjectAtPixels = function(position) {
		var minDist = Number.POSITIVE_INFINITY;
		var minDistObj = null;
		for (var o in this.objects) {
			var dist = this.objects[o].distToPixels(this, position);
			if (dist < minDist && dist < 10.0) {
				minDist = dist;
				minDistObj = this.objects[o];
			}
		}
		return minDistObj;
	}
	this.drawCircle = function(position, radius, fillStyle) {
		var context = this.getContext();

		context.strokeStyle = "#red";
		context.fillStyle = fillStyle;
		context.beginPath();
		context.arc(position.elements[0],position.elements[1],radius,0,Math.PI*2,true);
		context.closePath();
		//context.stroke();
		context.fill();
	}
	this.drawLine = function(startPosition, endPosition, strokeStyle) {
		var context = this.getContext();

		context.strokeStyle = strokeStyle;
		context.lineWidth = 5;
		context.beginPath();
		context.moveTo(startPosition.elements[0], startPosition.elements[1]);
		context.lineTo(endPosition.elements[0], endPosition.elements[1]);
		
		context.closePath();
		context.stroke();
	}
	this.render = function() {
		this.getContext().clearRect(0, 0, this.getCanvas().width, this.getCanvas().height);

		for (var o in this.objects) {
			this.objects[o].render(this);
		}
	}
}

function RenderablesVar() {
	this.Node = function(physicsNode) {
		this.render = function(renderer) {
			var fillStyle = this.isSelected ? "blue" : "black";
			renderer.drawCircle(renderer.physicsCoords2Pixels(this.physicsNode.position), 5, fillStyle);
		}
		this.distToPixels = function(renderer, position) {
			var myPix = renderer.physicsCoords2Pixels(this.physicsNode.position);
			// console.log("--");
			// console.log(this.physicsNode.position.elements);
			// console.log(position.elements);
			// console.log(myPix.elements);
			// console.log(myPix.subtract(position).modulus());
			return myPix.subtract(position).modulus();
		}
		this.setSelected = function(val) {
			this.isSelected = val;
		}
		this.setPixelPosition = function(renderer, position) {
			var ppos = renderer.pixels2PhysicsCoords(position);
			this.physicsNode.position = ppos;
		}
		// variables
		this.name = "renderableNode";
		this.physicsNode = physicsNode;
		this.isSelected = false;
	}
	this.Rod = function(physicsRod) {
		this.render = function(renderer) {
			var strokeStyle = this.isSelected ? "blue" : "red";
			renderer.drawLine(
				renderer.physicsCoords2Pixels(this.physicsRod.ports[0].node.position),
				renderer.physicsCoords2Pixels(this.physicsRod.ports[1].node.position),
				strokeStyle);
		}
		this.distToPixels = function(renderer, position) {
			var myPos = this.physicsRod.ports[0].node.position.add(this.physicsRod.ports[1].node.position).multiply(0.5);
			var myPix = renderer.physicsCoords2Pixels(myPos);
			return myPix.subtract(position).modulus();
		}
		this.setSelected = function(val) {
			this.isSelected = val;
		}
		this.setPixelPosition = function(renderer, position) {
		}
		//variables
		this.name = "renderableRod";
		this.physicsRod = physicsRod;
		this.isSelected = false;
	}
	this.Ball = function(physicsBall) {
		this.render = function(renderer) {
			renderer.drawCircle(renderer.physicsCoords2Pixels(this.physicsBall.node.position), renderer.physicsLength2Pixels(this.physicsBall.radius), "green");
		}
		this.distToPixels = function(renderer, position) {
			return Number.POSITIVE_INFINITY;
		}
		// variables
		this.name = "renderableBall";
		this.physicsBall = physicsBall;
	}
}

var Renderables = new RenderablesVar();
